package com.wangmeng.book.updater;

import com.wangmeng.book.dao.BaseDaoSupport;
import com.wangmeng.book.entity.*;
import com.wangmeng.book.utils.ConstValueUtils;
import com.wangmeng.book.utils.SpringContextManager;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.log4j.Logger;
import org.cyberneko.html.parsers.DOMParser;
import org.hibernate.engine.jdbc.BlobProxy;
import org.springframework.jdbc.core.JdbcTemplate;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

import java.io.ByteArrayOutputStream;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * User: 王猛
 * Date: 13-9-22
 */
public class BookFromSohu implements IBookUpdater {
    private static final Logger logger = Logger.getLogger(BookFromSohu.class);
    private static final String BASE_URL = "http://vip.book.sohu.com/all/?qianyue=0&mc=0&sc=0&tl=0&bs=0&ld=0&fl=0&vip=0&ord=6&page=#{page}";
    private static final int PAGE_SIZE = 30;
    private static final String URL_FIX = "http://vip.book.sohu.com";
    private static final String CHARSET_HTML = "gbk";

    public void updateList() {
        try {
            int page = 1;
            int maxPage = 1;
            BaseDaoSupport daoSupport = SpringContextManager.getContext().getBean(BaseDaoSupport.class);
            String checkSql = " and name = ? and author = ? ";
            Document doc = getDocument(BASE_URL.replace("#{page}", String.valueOf(page)));
            if (doc != null) {
                NodeList divList = doc.getElementsByTagName("DIV");
                for (int i = 0; i < divList.getLength(); i++) {
                    Node divNode = divList.item(i);
                    if (divNode.hasAttributes()) {
                        Node clsNode = divNode.getAttributes().getNamedItem("class");
                        if (clsNode != null && clsNode.getNodeValue().trim().equals("book_result_top")) {
                            NodeList spList = ((Element) divNode).getElementsByTagName("SPAN");
                            if (spList.getLength() > 0) {
                                String txt = spList.item(spList.getLength() - 1).getTextContent().trim();
                                String[] numStrList = txt.split("\\/");
                                maxPage = Integer.valueOf(numStrList[1].trim());
                            }
                        } else if (clsNode != null && clsNode.getNodeValue().trim().equals("book_result")) {
                            NodeList liList = ((Element) divNode).getElementsByTagName("LI");
                            for (int l = 0; l < liList.getLength(); l++) {
                                Node liNode = liList.item(l);
                                NodeList fontList = ((Element) liNode).getElementsByTagName("FONT");
                                if (fontList.getLength() == 0) {
                                    //如果有表示是VIP类型的，要付费的
                                    try {
                                        NodeList subDivList = ((Element) liNode).getElementsByTagName("DIV");
                                        String cateName = subDivList.item(1).getTextContent().trim();
                                        Node titleNode = subDivList.item(2);
                                        Node hrefNode = ((Element) titleNode).getElementsByTagName("A").item(0);
                                        String title = hrefNode.getTextContent().trim();
                                        String href = hrefNode.getAttributes().getNamedItem("href").getNodeValue().trim();
                                        Integer wordNum = Integer.valueOf(subDivList.item(3).getTextContent().trim());
                                        String author = subDivList.item(4).getTextContent().trim();
                                        List<BookDoc> bdList = daoSupport.listEntityByCondition(BookDoc.class, checkSql, new Object[]{title, author});
                                        if (bdList.size() == 0) {
                                            BookDoc bd = new BookDoc();
                                            bd.setName(title);
                                            bd.setCateName(cateName);
                                            bd.setSourceId(href);
                                            bd.setHref(URL_FIX + href);
                                            bd.setWordNum(wordNum);
                                            bd.setAuthor(author);
                                            bd.setFree(1);
                                            bd.setType(ConstValueUtils.BOOK_TYPE_COMMON);
                                            bd.setApproveStatus(ConstValueUtils.APPROVE_INIT);
                                            bd.setSourceType(ConstValueUtils.SOURCE_TYPE_SH);
                                            dirDetail(bd);
                                        }
                                    } catch (Exception ex) {
                                        logger.error(ex);
                                    }
                                } else {

                                }
                            }
                        }
                    }
                }
            }
            for (int sp = 2; sp <= maxPage; sp++) {
                doc = getDocument(BASE_URL.replace("#{page}", String.valueOf(sp)));
                if (doc != null) {
                    NodeList divList = doc.getElementsByTagName("DIV");
                    for (int i = 0; i < divList.getLength(); i++) {
                        Node divNode = divList.item(i);
                        if (divNode.hasAttributes()) {
                            Node clsNode = divNode.getAttributes().getNamedItem("class");
                            if (clsNode != null && clsNode.getNodeValue().trim().equals("book_result")) {
                                NodeList liList = ((Element) divNode).getElementsByTagName("LI");
                                for (int l = 0; l < liList.getLength(); l++) {
                                    Node liNode = liList.item(l);
                                    NodeList fontList = ((Element) liNode).getElementsByTagName("FONT");
                                    if (fontList.getLength() == 0) {
                                        try {
                                            //如果有表示是VIP类型的，要付费的
                                            NodeList subDivList = ((Element) liNode).getElementsByTagName("DIV");
                                            String cateName = subDivList.item(1).getTextContent().trim();
                                            Node titleNode = subDivList.item(2);
                                            Node hrefNode = ((Element) titleNode).getElementsByTagName("A").item(0);
                                            String title = hrefNode.getTextContent().trim();
                                            String href = hrefNode.getAttributes().getNamedItem("href").getNodeValue().trim();
                                            Integer wordNum = Integer.valueOf(subDivList.item(3).getTextContent().trim());
                                            String author = subDivList.item(4).getTextContent().trim();
                                            List<BookDoc> bdList = daoSupport.listEntityByCondition(BookDoc.class, checkSql, new Object[]{title, author});
                                            if (bdList.size() == 0) {
                                                BookDoc bd = new BookDoc();
                                                bd.setName(title);
                                                bd.setCateName(cateName);
                                                bd.setSourceId(href);
                                                bd.setHref(URL_FIX + href);
                                                bd.setWordNum(wordNum);
                                                bd.setAuthor(author);
                                                bd.setFree(1);
                                                bd.setType(ConstValueUtils.BOOK_TYPE_COMMON);
                                                bd.setApproveStatus(ConstValueUtils.APPROVE_INIT);
                                                bd.setSourceType(ConstValueUtils.SOURCE_TYPE_SH);
                                                dirDetail(bd);
                                            }
                                        } catch (Exception ex) {
                                            logger.error(ex);
                                        }
                                    } else {

                                    }
                                }
                            }
                        }
                    }
                }
            }
        } catch (Exception ex) {
            logger.error("SOHU列表更新异常", ex);
        }
    }

    private void dirDetail(BookDoc bd) {
        Document doc = getDocument(bd.getHref());
        if (doc != null) {
            bd.setHasIcon(false);
            NodeList divList = doc.getElementsByTagName("DIV");
            for (int i = 0; i < divList.getLength(); i++) {
                Node divNode = divList.item(i);
                if (divNode.hasAttributes()) {
                    Node clsNode = divNode.getAttributes().getNamedItem("class");
                    if (clsNode != null && clsNode.getNodeValue().trim().equals("book_first_left")) {
                        NodeList imgList = ((Element) divNode).getElementsByTagName("IMG");
                        if (imgList.getLength() > 0) {
                            String imgHref = imgList.item(0).getAttributes().getNamedItem("src").getNodeValue().trim();
                            byte[] data = downHttpData(imgHref);
                            if (data.length > 0) {
                                bd.setHasIcon(true);
                                bd.setIcon(BlobProxy.generateProxy(data));
                            }
                        }
                    } else if (clsNode != null && clsNode.getNodeValue().trim().equals("book_first_right")) {
                        NodeList liList = ((Element) divNode).getElementsByTagName("LI");
                        for (int l = 0; l < liList.getLength(); l++) {
                            String txt = liList.item(l).getTextContent().trim();
                            if (txt.startsWith("总点击：")) {
                                bd.setViewCount(Integer.valueOf(txt.substring(4).trim()));
                            } else if (txt.startsWith("状态：")) {
                                String st = txt.substring(3).trim();
                                bd.setStatus(st.equals("连载中") ? ConstValueUtils.STATUS_CONTINUE : ConstValueUtils.STATUS_FINISHED);
                                break;
                            }
                        }
                        NodeList subDivList = ((Element) divNode).getElementsByTagName("DIV");
                        String summary = subDivList.item(3).getChildNodes().item(0).getTextContent().trim();
                        bd.setBookBrief(summary);
                        break;
                    }
                }
            }
            //保存记录
            BaseDaoSupport daoSupport = SpringContextManager.getContext().getBean(BaseDaoSupport.class);
            bd.setUpdateTime(new Date());
            daoSupport.saveEntity(bd);
            //保存tag
            JdbcTemplate jt = SpringContextManager.getContext().getBean(JdbcTemplate.class);
            String checkTagSql = "select oid from book_document_tag where tag_name = ? ";
            List<Map<String, Object>> tagDbList = jt.queryForList(checkTagSql, new Object[]{bd.getName()});
            int tagId;
            if (tagDbList.size() > 0) {
                tagId = ((Number) tagDbList.get(0).get("oid")).intValue();
            } else {
                BookDocTag bt = new BookDocTag();
                bt.setName(bd.getName());
                daoSupport.saveEntity(bt);
                tagId = bt.getId();
            }
            BookDocTagRelation tr = new BookDocTagRelation();
            tr.setBookId(bd.getId());
            tr.setTagId(tagId);
            daoSupport.saveEntity(tr);
            tagDbList = jt.queryForList(checkTagSql, new Object[]{bd.getAuthor()});
            if (tagDbList.size() > 0) {
                tagId = ((Number) tagDbList.get(0).get("oid")).intValue();
            } else {
                BookDocTag bt = new BookDocTag();
                bt.setName(bd.getAuthor());
                daoSupport.saveEntity(bt);
                tagId = bt.getId();
            }
            tr = new BookDocTagRelation();
            tr.setBookId(bd.getId());
            tr.setTagId(tagId);
            daoSupport.saveEntity(tr);
        }
    }

    public int loadContent(BookDoc bd) {
        try {
            Document doc = getDocument(bd.getHref());
            if (doc != null) {
                BaseDaoSupport daoSupport = SpringContextManager.getContext().getBean(BaseDaoSupport.class);
                NodeList divList = doc.getElementsByTagName("DIV");
                for (int i = 0; i < divList.getLength(); i++) {
                    Node divNode = divList.item(i);
                    if (divNode.hasAttributes()) {
                        Node clsNode = divNode.getAttributes().getNamedItem("class");
                        if (clsNode != null && clsNode.getNodeValue().trim().equals("booklist_sub_box")) {
                            NodeList aList = ((Element) divNode).getElementsByTagName("A");
                            if (aList.getLength() > 0) {
                                //添加Section
                                BookDocSection bds = new BookDocSection();
                                bds.setName("正文");
                                bds.setBookId(bd.getId());
                                bds.setOrder(1);
                                bds.setFrom(1);
                                bds.setTo(aList.getLength());
                                bds.setStatus(0);
                                daoSupport.saveEntity(bds);
                                for (int a = 0; a < aList.getLength(); a++) {
                                    Node aNode = aList.item(a);
                                    String title = aNode.getTextContent().trim();
                                    String href = URL_FIX + aNode.getAttributes().getNamedItem("href").getNodeValue().trim();
                                    Document detail = getDocument(href);
                                    if (detail != null) {
                                        Element contentDiv = detail.getElementById("contentdiv");
                                        NodeList pList = contentDiv.getElementsByTagName("P");
                                        StringBuffer content = new StringBuffer();
                                        for (int p = 0; p < pList.getLength(); p++) {
                                            String pt = pList.item(p).getTextContent().trim();
                                            if (pt.length() > 0) {
                                                content.append("<p>").append(pt).append("</p>");
                                            }
                                        }
                                        BookDocPart bdp = new BookDocPart();
                                        bdp.setSectionId(bds.getId());
                                        bdp.setTitle(title);
                                        bdp.setOrder(a + 1);
                                        bdp.setStoreType(ConstValueUtils.STORE_TYPE_DB);
                                        bdp.setContent(content.toString());
                                        bdp.setUpdateTime(new Date());
                                        daoSupport.saveEntity(bdp);
                                    }
                                }
                            }
                            break;
                        }
                    }
                }
            }
        } catch (Exception ex) {
            return ConstValueUtils.CODE_EXCEPTION;
        }
        return ConstValueUtils.CODE_SUCCESS;
    }

    public int updateContent(BookDoc bd) {
        try {
            Document doc = getDocument(bd.getHref());
            if (doc != null) {
                BaseDaoSupport daoSupport = SpringContextManager.getContext().getBean(BaseDaoSupport.class);
                JdbcTemplate jt = SpringContextManager.getContext().getBean(JdbcTemplate.class);
                List<BookDocSection> sectionList = daoSupport.listEntityByCondition(BookDocSection.class, " and bookId = ? order by order asc", new Object[]{bd.getId()});
                String maxPartSql = "select IFNULL(max(part_order),0) mo from book_document_part where section_id in ( select oid from book_document_section where book_id = ? )";
                int maxPartNum = jt.queryForInt(maxPartSql, new Object[]{bd.getId()});
                int currentPageNum = maxPartNum;
                NodeList divList = doc.getElementsByTagName("DIV");
                for (int i = 0; i < divList.getLength(); i++) {
                    Node divNode = divList.item(i);
                    if (divNode.hasAttributes()) {
                        Node clsNode = divNode.getAttributes().getNamedItem("class");
                        if (clsNode != null && clsNode.getNodeValue().trim().equals("booklist_sub_box")) {
                            NodeList aList = ((Element) divNode).getElementsByTagName("A");
                            if (aList.getLength() > 0) {
                                //添加Section
                                int sId = 0;
                                if (sectionList.size() == 0) {
                                    BookDocSection bds = new BookDocSection();
                                    bds.setName("正文");
                                    bds.setBookId(bd.getId());
                                    bds.setOrder(1);
                                    bds.setFrom(1);
                                    bds.setTo(aList.getLength());
                                    bds.setStatus(0);
                                    daoSupport.saveEntity(bds);
                                    sId = bds.getId();
                                } else {
                                    sId = sectionList.get(0).getId();
                                }
                                for (int a = 0; a < aList.getLength(); a++) {
                                    if ((a + 1) >= maxPartNum) {
                                        Node aNode = aList.item(a);
                                        String title = aNode.getTextContent().trim();
                                        String href = URL_FIX + aNode.getAttributes().getNamedItem("href").getNodeValue().trim();
                                        Document detail = getDocument(href);
                                        if (detail != null) {
                                            Element contentDiv = detail.getElementById("contentdiv");
                                            NodeList pList = contentDiv.getElementsByTagName("P");
                                            StringBuffer content = new StringBuffer();
                                            for (int p = 0; p < pList.getLength(); p++) {
                                                String pt = pList.item(p).getTextContent().trim();
                                                if (pt.length() > 0) {
                                                    content.append("<p>").append(pt).append("</p>");
                                                }
                                            }
                                            BookDocPart bdp = new BookDocPart();
                                            bdp.setSectionId(sId);
                                            bdp.setTitle(title);
                                            bdp.setOrder(a + 1);
                                            bdp.setStoreType(ConstValueUtils.STORE_TYPE_DB);
                                            bdp.setContent(content.toString());
                                            bdp.setUpdateTime(new Date());
                                            daoSupport.saveEntity(bdp);
                                            currentPageNum = a + 1;
                                        }
                                    }
                                }
                            }
                            break;
                        }
                    }
                }
                return currentPageNum - maxPartNum;
            }
        } catch (Exception ex) {
            return ConstValueUtils.CODE_SUCCESS;
        }
        return ConstValueUtils.CODE_SUCCESS;
    }

    private Document getDocument(String url) {
        try {
            HttpClient hc = new DefaultHttpClient();
            hc.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, 60000);
            hc.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 30000);
            HttpGet hg = new HttpGet(url);
            HttpResponse response = hc.execute(hg);
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                DOMParser htc = new DOMParser();
                htc.setProperty("http://cyberneko.org/html/properties/default-encoding", CHARSET_HTML);
                htc.parse(new InputSource(response.getEntity().getContent()));
                hc.getConnectionManager().shutdown();
                return htc.getDocument();
            }
        } catch (Exception e) {
            logger.error("解析Html异常:" + url, e);
        }
        return null;
    }

    private byte[] downHttpData(String url) {
        try {
            HttpClient hc = new DefaultHttpClient();
            hc.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, 60000);
            hc.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 30000);
            HttpGet hg = new HttpGet(url);
            HttpResponse response = hc.execute(hg);
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                ByteArrayOutputStream bout = new ByteArrayOutputStream();
                response.getEntity().writeTo(bout);
                return bout.toByteArray();
            }
        } catch (Exception e) {
            logger.error("解析Html异常:" + url, e);
        }
        return null;
    }
}
